package com.lm.webserver;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lm.pojo.Message;
import com.lm.pojo.MsgStore;
import com.lm.service.MsgStoreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint("/chat/webSocket/{uid}")
@Component
public class WebSocketServer {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);

	 //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger onlineNum = new AtomicInteger();

    //concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象。
    private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();

    /**
     * 解决websocket无法注入bean
     */
    private static MsgStoreService msgStoreService;

    @Autowired
    public void setMsgStoreService(MsgStoreService msgStoreService){
        WebSocketServer.msgStoreService = msgStoreService;
    }

    //发送消息
    public void sendMessage(Session session, String message) throws IOException {
        if(session != null && session.isOpen()){
            synchronized (session) {
                try {
                    session.getBasicRemote().sendText(message);
                    logger.debug("消息发送成功: {}", message);
                } catch (IOException e) {
                    logger.error("发送消息失败: {}", e.getMessage());
                    throw e;
                }
            }
        } else {
            logger.warn("会话不存在或已关闭，无法发送消息");
        }
    }
    //给指定用户uid发送信息
    public void sendInfo(String uid, String message){
        Session session = sessionPools.get(uid);
        try {
            if (session != null && session.isOpen()) {
                sendMessage(session, message);
            } else {
                logger.warn("用户 {} 的WebSocket会话不存在或已关闭", uid);
            }
        } catch (Exception e){
            logger.error("发送消息给用户 {} 失败: {}", uid, e.getMessage());
        }
    }

    // 群发消息
    public void broadcast(String message){
    	for (Session session: sessionPools.values()) {
            try {
                if (session != null && session.isOpen()) {
                    sendMessage(session, message);
                }
            } catch(Exception e){
                logger.error("群发消息失败: {}", e.getMessage());
                continue;
            }
        }
    }

    //建立连接成功调用
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "uid") String uid){
        try {
            // 设置会话属性
            session.setMaxIdleTimeout(300000); // 5分钟超时
            session.setMaxBinaryMessageBufferSize(8192);
            session.setMaxTextMessageBufferSize(8192);
            
            sessionPools.put(uid, session);
            addOnlineCount();
            logger.info("用户 {} 加入webSocket！当前人数为 {}", uid, onlineNum);
            
            // 发送连接确认消息
            Message connected = new Message();
            connected.setSenderUid("system");
            connected.setReceiverUid(uid);
            connected.setMsgContent("connected");
            connected.setMsgType(0);
            connected.setMsgTime(new Date());
            sendInfo(uid, JSON.toJSONString(connected));
        } catch (Exception e) {
            logger.error("WebSocket连接建立失败: {}", e.getMessage());
        }
    }

    //关闭连接时调用
    @OnClose
    public void onClose(@PathParam(value = "uid") String uid){
        try {
            Session session = sessionPools.get(uid);
            if (session != null) {
                session.close();
            }
            sessionPools.remove(uid);
            subOnlineCount();
            logger.info("用户 {} 断开webSocket连接！当前人数为 {}", uid, onlineNum);
        } catch (Exception e) {
            logger.error("WebSocket连接关闭失败: {}", e.getMessage());
        }
    }

    //收到客户端信息后，根据接收人的username把消息推下去或者群发
    @OnMessage
    public void onMessage(String message) throws IOException{
        try {
            logger.debug("收到消息: {}", message);
            // 解析前端发送的消息格式
            JSONObject jsonObject = JSON.parseObject(message);
            Message msg = new Message();
            msg.setSenderUid(jsonObject.getString("from"));
            msg.setReceiverUid(jsonObject.getString("to"));
            msg.setMsgContent(jsonObject.getString("text"));
            msg.setMsgType(1); // 1表示普通消息
            msg.setMsgTime(new Date());
            
            // 处理心跳消息
            if ("heartbeat".equals(msg.getMsgContent())) {
                Message response = new Message();
                response.setSenderUid("system");
                response.setReceiverUid(msg.getSenderUid());
                response.setMsgContent("heartbeat");
                response.setMsgType(0);
                response.setMsgTime(new Date());
                sendInfo(msg.getSenderUid(), JSON.toJSONString(response));
                return;
            }

            // 处理普通消息
            if (msgStoreService == null) {
                SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
            }

            Session touser = sessionPools.get(msg.getReceiverUid());
            if (touser == null || !touser.isOpen()){
                logger.info("用户 {} 不在线，消息将保存到数据库", msg.getReceiverUid());
                Integer msgid = msgStoreService.saveMessageUnRead(msg);
                msg.setId(msgid);
            } else {
                Integer msgid = msgStoreService.saveMessageUnRead(msg);
                msg.setId(msgid);
                sendInfo(msg.getReceiverUid(), JSON.toJSONString(msg));
            }
        } catch (Exception e) {
            logger.error("处理消息失败: {}", e.getMessage());
            throw new IOException("消息处理失败", e);
        }
    }


    //错误时调用
    @OnError
    public void onError(Session session, Throwable throwable){
        logger.error("WebSocket发生错误: {}", throwable.getMessage());
        if (session != null) {
            try {
                session.close();
            } catch (IOException e) {
                logger.error("关闭错误的WebSocket连接失败: {}", e.getMessage());
            }
        }
    }

    public static void isMsg(String uid){
        try {
            List<MsgStore> msgList = msgStoreService.isHasUnReadMsg(uid);
            if (msgList.isEmpty()){
                logger.info("用户 {} 没有新消息", uid);
            } else {
                logger.info("用户 {} 有 {} 条新消息", uid, msgList.size());
            }
        } catch (Exception e) {
            logger.error("检查新消息失败: {}", e.getMessage());
        }
    }

    //发送信息数提示
    public void sendtips(String uid){
        try {
            Session session = sessionPools.get(uid);
            if (session != null && session.isOpen()) {
                int msgCount = msgStoreService.getUnReadMsgCount(uid);
                Message message = new Message();
                message.setSenderUid("system");
                message.setReceiverUid(uid);
                message.setMsgContent(String.valueOf(msgCount));
                message.setMsgType(0);
                message.setMsgTime(new Date());
                sendMessage(session, JSON.toJSONString(message));
            }
        } catch (Exception e) {
            logger.error("发送消息提示失败: {}", e.getMessage());
        }
    }

    public static void addOnlineCount(){
        onlineNum.incrementAndGet();
    }

    public static void subOnlineCount() {
        onlineNum.decrementAndGet();
    }
    
    public static AtomicInteger getOnlineNumber() {
        return onlineNum;
    }
    
    public static ConcurrentHashMap<String, Session> getSessionPools() {
        return sessionPools;
    }
}
